/* eslint-disable max-lines */
/**
 * 上下联动图（共享滚动条）
 * LinkageChartsC (reactCharts)
 * @author zxy
 * @date  2020-12-09
 */
import accounting from 'accounting';
import { Spin } from 'antd';
import ReactEcharts from 'echarts-for-react';
import _ from 'lodash';
import PropTypes from 'prop-types';
import React from 'react';

import { constant } from './constant';

import Color from '../../../css/colors';
import { NoDataC } from '@/src/components/other';

class LinkageChartsC extends React.Component {
  // 入参默认值设置
  static defaultProps = {
    xAxis: undefined,
    yAxis: undefined,
    series: undefined,
    type: 'line', // 默认折线图
    height: '600px', // 图形高度默认为父节点的100%
    width: '100%', // 图形宽度默认为父节点的100%
    dataZoom: false, // 默认无横向滚动轴
    colors: Color.echart, // 默认系统色
    title: '', // 标题默认为空
    boundaryGap: true, // 默认坐标轴两边留白
    showBorder: false, // 默认不展示外边框
    toolTipFormat: undefined, // 默认按自定义的提示信息样式展示
    toolTipDataFormat: undefined,
    gridLeft: 60, // 默认左轴距离左侧距离为60
    gridRight: 60, // 默认右轴距离右侧距离为60
    isMarkPoint: false, // 是否显示最大最小值
  };

  debtAndProfitColor = Color.debtAndProfit.area1; // type为收益负债模式时，固定显示的颜色

  // 返回option
  getOption = (legend, series, dataZoom, visualMap) => {
    const { colors, title, xAxis, toolTipFormat, toolTipDataFormat, boundaryGap, gridLeft, gridRight, yAxis, height } = this.props;
    // 每一项Y轴的固定配置
    const yAxisElement = {
      name: undefined, // 坐标轴显示名称
      type: 'value',
      nameTextStyle: {
        // Y轴名称文本样式
        color: Color.echartItems.title,
        fontSize: 12,
      },
      axisLine: {
        // Y轴轴线样式
        show: false,
        lineStyle: {
          color: Color.echartItems.yAxisLine,
        },
      },
      axisTick: {
        // Y轴间隔小线段样式
        show: false,
      },
      axisLabel: {
        // Y轴文本样式
        color: Color.echartItems.yAxisLabel,
        fontSize: 12,
        margin: 4, // 与纵轴的距离
      },
      splitNumber: 4, // 坐标轴的分割段数，需要注意的是这个分割段数只是个预估值，最后实际显示的段数会在这个基础上根据分割后坐标轴刻度显示的易读程度作调整
      splitLine: {
        // Y轴分割线样式
        show: true,
        lineStyle: {
          type: 'dashed',
          color: Color.echartItems.splitLine,
        },
      },
      scale: true,
    };
    // 默认是上下两个Y轴
    const yAxisTemp = yAxis || [{ gridIndex: 0 }, { gridIndex: 1 }];
    const yAxisVal = yAxisTemp.map((item) => ({ ...yAxisElement, ...item }));

    return {
      // 调色盘颜色列表
      color: colors,
      backgroundColor: Color.echartItems.bgColor, // echarts整个画布的背景色
      // 主标题和副标题
      title: {
        show: !!title,
        left: '20',
        top: 20,
        text: title,
        textStyle: {
          color: Color.echartItems.title,
          fontSize: 14,
          fontWeight: 'normal',
          lineHeight: 20,
        },
      },
      axisPointer: {
        link: {
          xAxisIndex: 'all',
        },
      },
      // 鼠标移动上去提示信息
      tooltip: {
        trigger: 'axis',
        show: true,
        axisPointer: {
          type: 'line', // tooltip展示十字型
          crossStyle: {
            color: Color.echartItems.tooltipCross,
          },
          label: {
            show: false,
            backgroundColor: Color.echartItems.tooltipBg,
            color: Color.echartItems.tooltipLabel,
            padding: [7, 7, 5, 7],
          },
        },
        formatter:
          toolTipFormat ||
          ((params) => {
            let str = `<div style="color:${Color.echartItems.tooltipLabel}">`;
            str += `<div style="margin-bottom:12px">${params[0].name}</div>`;

            params.map((item, index) => {
              let { value } = item;
              // 根据seriesName，去series匹配，找出对应的yAxisIndex
              let toFixed;
              series.forEach((element) => {
                if (element.name === item.seriesName) {
                  toFixed = element.toFixed;
                }
              });
              if (toFixed && typeof value === 'number') {
                // 每个选项展示格式 保留小数位
                // 转换前必须是数字类型，（排除null，undefined，空字符串）
                value = accounting.formatNumber(Number(value), toFixed);
              }
              str += `<div style="display:flex;align-items:center;margin-top:8px">
                      <div style="border:1px solid rgb(255,255,255);width:10px;height:10px;border-radius:50%;background-color:${item.color};margin-right:8px"></div>
                      ${item.seriesName}： ${toolTipDataFormat ? toolTipDataFormat[index](value, item) : value}
                    </div>`;
            });
            str += '</div>';
            return str;
          }),
        padding: [12, 12, 12, 12],
        confine: true,
        backgroundColor: Color.echartItems.tooltipBgColor,
        extraCssText: `box-shadow: 0px 2px 12px 0px ${Color.echartItems.tooltipBgShadow};border-radius: 4px;opacity: 0.65;font-size: 12px;font-family: PingFangSC-Regular, PingFang SC;font-weight: 400;`,
      },
      // 图例
      legend: {
        show: true,
        data: legend,
        bottom: 13,
        right: 40,
        textStyle: {
          color: Color.echartItems.legend,
          fontSize: 12,
        },
        itemWidth: 20,
        itemHeight: 14,
        borderRadius: [0, 0, 0, 0],
      },
      // 直角坐标系内绘图网格
      grid: [
        {
          left: gridLeft,
          right: gridRight,
          top: 50,
          height: dataZoom ? (parseInt(height) - 210) / 2 : (parseInt(height) - 200) / 2,
        },
        {
          left: gridLeft,
          right: gridRight,
          top: dataZoom ? 100 + (parseInt(height) - 210) / 2 : 100 + (parseInt(height) - 200) / 2,
          height: dataZoom ? (parseInt(height) - 210) / 2 : (parseInt(height) - 200) / 2,
        },
      ],
      // 横轴
      xAxis: [
        {
          gridIndex: 0,
          type: 'category',
          show: false,
          boundaryGap, // 标记横轴左右是否有空隙
          data: xAxis,
          axisLine: {
            lineStyle: {
              color: Color.echartItems.xAxisLine,
            },
          },
          axisTick: {
            show: false,
          },
          axisLabel: {
            color: Color.echartItems.xAxisLabel,
            margin: 6, // 与横轴的距离
            fontSize: 12,
          },
        },
        {
          gridIndex: 1,
          type: 'category',
          boundaryGap, // 标记横轴左右是否有空隙
          data: xAxis,
          axisLine: {
            lineStyle: {
              color: Color.echartItems.xAxisLine,
            },
          },
          axisTick: {
            show: false,
          },
          axisLabel: {
            color: Color.echartItems.xAxisLabel,
            margin: 6, // 与横轴的距离
            fontSize: 12,
          },
        },
      ],
      // 纵轴
      yAxis: yAxisVal,
      // 横向滚动条
      dataZoom: dataZoom
        ? {
            ...dataZoom,
            bottom: 41,
            height: 40,
            left: 20,
            right: 20,
            handleColor: Color.echartItems.dataZoomHandBg, // 滑动图标的颜色
            borderColor: Color.echartItems.dataZoomBorderBg, // 边框颜色
            backgroundColor: Color.echartItems.dataZoomBg, // 滚动条未选中区域的背景颜色
            dataBackground: {
              lineStyle: {
                color: Color.echartItems.dataZoomShadowBg,
              },
              areaStyle: {
                color: Color.echartItems.dataZoomShadowBg, // 滚动条数据阴影区域的背景颜色
                shadowColor: Color.echartItems.dataZoomShadowBg, // 滚动条数据阴影区域的背景颜色
              },
            },
            fillerColor: Color.echartItems.dataZoomChoosedBg, // 滚动条选中区域的背景颜色
          }
        : [],
      // 数据
      series,
      visualMap,
    };
  };

  render() {
    const { series, xAxis, width, height, dataZoom, showBorder, barMaxWidth, isMarkPoint } = this.props;

    const legend = []; // 图例
    let seriesVals = []; // series
    let zoom, // 横向滚动轴
      visualMap; // 正红负绿区域块设置
    const initStatus = series && xAxis; // 标记是否达到初始化状态(true:可以初始化图表，false：还未获取到数据)

    if (initStatus) {
      // 根据传参，自动生成series数据和图例数据
      seriesVals =
        series &&
        series.map((item, index) => {
          // 搜集图例数据
          legend.push(item.name);

          // 每个元素
          let seriesItem = _.cloneDeep(item);
          switch (item.type ? item.type : 'line') {
            case 'bar': // 柱状图
              if (item.debtAndProfit) {
                const newData = [];
                for (let i = 0; i < item.data.length; i++) {
                  const element = item.data[i];
                  newData.push({
                    value: element,
                    itemStyle: {
                      color: element != undefined && element > 0 ? this.debtAndProfitColor[0] : this.debtAndProfitColor[1],
                    },
                  });
                }
                seriesItem.data = newData;
              }
              seriesItem = {
                ...seriesItem,
                type: 'bar',
                barMaxWidth, // 默认最大宽度是20，正常情况下自适应
                markPoint: isMarkPoint
                  ? {
                      // 自定义最大最小值
                      data: [
                        {
                          type: 'max',
                          name: 'bar-max',
                          itemStyle: { color: '#F4423A' },
                          symbol: `image://${constant.top}`,
                          symbolSize: [16, 16],
                          symbolOffset: [0, -14],
                          label: {
                            color: '#F4423A',
                            offset: [1, -16],
                          },
                        },
                        {
                          type: 'min',
                          name: 'bar-min',
                          itemStyle: { color: '#2FB098' },
                          symbol: `image://${constant.bottom}`,
                          symbolSize: [16, 16],
                          symbolOffset: [0, -14],
                          label: {
                            color: '#2FB098',
                            offset: [1, -16],
                          },
                        },
                      ],
                    }
                  : null,
              };
              break;
            case 'area': // 面积图
              if (item.debtAndProfit) {
                visualMap = {
                  show: false,
                  pieces: [
                    {
                      gt: -100,
                      lte: 0,
                      color: this.debtAndProfitColor[1],
                    },
                    {
                      gt: 0,
                      lte: 100,
                      color: this.debtAndProfitColor[0],
                    },
                  ],
                  seriesIndex: index,
                };
              }
              seriesItem = {
                ...seriesItem,
                type: 'line',
                areaStyle: {
                  // opacity: 0.3,
                },
                showSymbol: false,
                smooth: true,
                markPoint: isMarkPoint
                  ? {
                      data: [
                        {
                          type: 'max',
                          name: 'line-max',
                          itemStyle: { color: '#F4423A' },
                          symbol: `image://${constant.top}`,
                          symbolSize: [16, 16],
                          symbolOffset: [0, -14],
                          label: {
                            color: '#F4423A',
                            offset: [1, -16],
                          },
                        },
                        {
                          type: 'min',
                          name: 'line-min',
                          itemStyle: { color: '#2FB098' },
                          symbol: `image://${constant.bottom}`,
                          symbolSize: [16, 16],
                          symbolOffset: [0, -14],
                          label: {
                            color: '#2FB098',
                            offset: [1, -16],
                          },
                        },
                      ],
                    }
                  : null,
              };
              break;
            case 'point': // 点状图
              seriesItem = {
                ...seriesItem,
                type: 'line',
                symbol: 'circle',
                symbolSize: 15,
                lineStyle: {
                  opacity: 0,
                },
                markPoint: isMarkPoint
                  ? {
                      data: [
                        {
                          type: 'max',
                          name: 'line-max',
                          itemStyle: { color: '#F4423A' },
                          symbol: `image://${constant.top}`,
                          symbolSize: [16, 16],
                          symbolOffset: [0, -14],
                          label: {
                            color: '#F4423A',
                            offset: [1, -16],
                          },
                        },
                        {
                          type: 'min',
                          name: 'line-min',
                          itemStyle: { color: '#2FB098' },
                          symbol: `image://${constant.bottom}`,
                          symbolSize: [16, 16],
                          symbolOffset: [0, -14],
                          label: {
                            color: '#2FB098',
                            offset: [1, -16],
                          },
                        },
                      ],
                    }
                  : null,
              };
              break;
            case 'lineStack': // 线性堆叠图
              seriesItem = {
                ...seriesItem,
                type: 'line',
                stack: '总量',
                showSymbol: false,
                markPoint: isMarkPoint
                  ? {
                      data: [
                        {
                          type: 'max',
                          name: 'line-max',
                          itemStyle: { color: '#F4423A' },
                          symbol: `image://${constant.top}`,
                          symbolSize: [16, 16],
                          symbolOffset: [0, -14],
                          label: {
                            color: '#F4423A',
                            offset: [1, -16],
                          },
                        },
                        {
                          type: 'min',
                          name: 'line-min',
                          itemStyle: { color: '#2FB098' },
                          symbol: `image://${constant.bottom}`,
                          symbolSize: [16, 16],
                          symbolOffset: [0, -14],
                          label: {
                            color: '#2FB098',
                            offset: [1, -16],
                          },
                        },
                      ],
                    }
                  : null,
              };
              break;
            case 'areaStack': // 面积堆叠图
              seriesItem = {
                ...seriesItem,
                type: 'line',
                stack: '总量',
                areaStyle: {},
                lineStyle: {
                  width: 0,
                },
                showSymbol: false,
                markPoint: isMarkPoint
                  ? {
                      data: [
                        {
                          type: 'max',
                          name: 'line-max',
                          itemStyle: { color: '#F4423A' },
                          symbol: `image://${constant.top}`,
                          symbolSize: [16, 16],
                          symbolOffset: [0, -14],
                          label: {
                            color: '#F4423A',
                            offset: [1, -16],
                          },
                        },
                        {
                          type: 'min',
                          name: 'line-min',
                          itemStyle: { color: '#2FB098' },
                          symbol: `image://${constant.bottom}`,
                          symbolSize: [16, 16],
                          symbolOffset: [0, -14],
                          label: {
                            color: '#2FB098',
                            offset: [1, -16],
                          },
                        },
                      ],
                    }
                  : null,
              };
              break;
            case 'barStack': // 柱状堆叠图
              seriesItem = {
                ...seriesItem,
                type: 'bar',
                barMaxWidth, // 默认最大宽度是20，正常情况下自适应
                stack: '总量',
                markPoint: isMarkPoint
                  ? {
                      data: [
                        {
                          type: 'max',
                          name: 'line-max',
                          itemStyle: { color: '#F4423A' },
                          symbol: `image://${constant.top}`,
                          symbolSize: [16, 16],
                          symbolOffset: [0, -14],
                          label: {
                            color: '#F4423A',
                            offset: [1, -16],
                          },
                        },
                        {
                          type: 'min',
                          name: 'line-min',
                          itemStyle: { color: '#2FB098' },
                          symbol: `image://${constant.bottom}`,
                          symbolSize: [16, 16],
                          symbolOffset: [0, -14],
                          label: {
                            color: '#2FB098',
                            offset: [1, -16],
                          },
                        },
                      ],
                    }
                  : null,
              };
              break;
            default: // 默认是line
              seriesItem = {
                ...seriesItem,
                type: 'line',
                showSymbol: false,
                // smooth: true,
                markPoint: isMarkPoint
                  ? {
                      data: [
                        {
                          type: 'max',
                          name: 'line-max',
                          itemStyle: { color: '#F4423A' },
                          symbol: `image://${constant.top}`,
                          symbolSize: [16, 16],
                          symbolOffset: [0, -14],
                          label: {
                            color: '#F4423A',
                            offset: [1, -16],
                          },
                        },
                        {
                          type: 'min',
                          name: 'line-min',
                          itemStyle: { color: '#2FB098' },
                          symbol: `image://${constant.bottom}`,
                          symbolSize: [16, 16],
                          symbolOffset: [0, -14],
                          label: {
                            color: '#2FB098',
                            offset: [1, -16],
                          },
                        },
                      ],
                    }
                  : null,
              };
              break;
          }

          return seriesItem;
        });

      // 根据入参设置横向滚动条
      if (dataZoom) {
        if (typeof dataZoom === 'boolean') {
          zoom = {
            start: 0,
            end: 100,
          };
        } else {
          zoom = {
            start: dataZoom.startValue,
            end: dataZoom.endValue,
          };
        }
        zoom = {
          ...zoom,
          type: 'slider',
          xAxisIndex: [0, 1],
          realtime: true,
        };
      }
    }

    return (
      <div style={{ border: showBorder && `1px solid ${Color.echartItems.border}`, width }}>
        <Spin spinning={!initStatus} tip='加载中...'>
          {initStatus ? (
            series.length > 0 && xAxis.length > 0 ? (
              <ReactEcharts
                option={this.getOption(legend, seriesVals, zoom, visualMap)}
                style={{ height, width }}
                // 是否不跟之前设置的 option 进行合并，默认为 false，即合并。
                notMerge={true}
                onEvents={{
                  legendselectchanged: this.legendselectchanged,
                  click: (e) => {
                    this.props.click && this.props.click(e);
                  },
                  mouseover: (e) => {
                    this.props.mouseover && this.props.mouseover(e);
                  },
                  mouseout: (e) => {
                    this.props.mouseout && this.props.mouseout(e);
                  },
                }}
                ref={this.initEchartsEvent}
              />
            ) : (
              <NoDataC />
            )
          ) : (
            <div style={{ height, width }} />
          )}
        </Spin>
      </div>
    );
  }
}

/*
备注：
  当xAxis和series值为null或undefined时，显示loading状态
  当xAxis和series值为空数组[]时，显示“暂无数据”
  当xAxis和series值为有值的数组时，正常实现图形
    'line',     // 折线图
    'bar',      // 柱状图
    'area',     // 面积图
    'point',    // 点状图（不是散点图，是折线图去掉线条，只留点）
    'lineStack',// 线性堆叠图
    'areaStack',// 面积堆叠图
    'barStack', // 柱状堆叠图
*/
LinkageChartsC.propsTypes = {
  xAxis: PropTypes.array, // 横轴数据（字符串数组）
  yAxis: PropTypes.array, // 纵轴配置（非样式配置）[{gridIndex:0,name:xxx},{gridIndex:1,name:xxx}]
  series: PropTypes.array, // 纵轴数据（[{name:'',data:[], xAxisIndex:'默认是0',yAxisIndex:'默认是0',type:'默认是type中定义的类型',debtAndProfit:'是否按正红负绿展示'},...]）
  height: PropTypes.oneOfType([
    // 图表高度（百分比、数值、auto(自动根据图例数量计算高度)）
    PropTypes.string,
    PropTypes.number,
  ]),
  width: PropTypes.oneOfType([
    // 图表宽度（百分比或数值）
    PropTypes.string,
    PropTypes.number,
  ]),
  dataZoom: PropTypes.oneOfType([
    // 是否有横向滚动轴（{startValue: 0,endValue: 5}）
    PropTypes.bool,
    PropTypes.object,
  ]),
  colors: PropTypes.array, // 图表颜色
  title: PropTypes.string, // 标题
  toolTipFormat: PropTypes.func, // 提示框内容显示格式处理
  toolTipDataFormat: PropTypes.array, // 数据在提示框中显示的格式（与所在纵轴位置一致，从左向右，每一项用func表示，如[value=>parseInt(value)}, value=>value+'%',...]，，没有的项用空位表示）
  boundaryGap: PropTypes.bool, // 坐标轴两边留白策略
  showBorder: PropTypes.bool, // 是否显示图形外层边框
  gridLeft: PropTypes.number, // 左轴距离左侧的距离
  gridRight: PropTypes.number, // 右轴距离右侧的距离
  isMarkPoint: PropTypes.bool, // 是否显示最大最小值图标
};

export default LinkageChartsC;
